#include <iostream>

// 1、内联函数就是相当于宏替换，但是它是有类型检查的函数
// 2、inline 关键字告诉编译器建议展开调用，听不听看编译器的意思
// 3、inline 函数可以调试，宏不行
// 4、inline 函数可以递归，宏不行
// 5、inline 函数可以有默认参数，宏不行
// 6、inline 函数可以重载，宏不行
// 7、inline 函数可以是模板，宏不行
// 8、inline 函数不会引起命名空间污染，宏会

/* 1. 宏版本 */
#define ADD_M(a, b) ((a) + (b))

/* 2. inline 函数版本 */
inline int add(int a, int b = 2)
{
    return a + b;
}

/* 3. 模板 inline 函数，可接受不同整数类型 */
template <class T>
inline T addT(T a, T b)
{
    return a + b;
}

int main()
{
    int x = 1, y = 2;

    int r1 = ADD_M(x, y); // 文本替换 → ((x++) + (y))  x 被加了 1 次
    int r2 = add(x, y);

    std::cout << "r1=" << r1 << " x=" << x << '\n';
    std::cout << "r2=" << r2 << " x=" << x << '\n';
    std::cout << "add(3)=" << add(3) << '\n'; // 使用默认参数
    // double d = ADD_M(3.5, 2.1);     // 能跑，但宏无类型
    double d = addT(3.5, 2.1);      // 模板实例化出 addT<double>
    std::cout << "d=" << d << '\n'; // d=5.6
    /* --------- 调试 --------- */
    // 在 gdb/VS 里可以对 add/addT 单步，看不到 ADD_M
    return 0;
}